#ifndef __IERROR_H__
#define __IERROR_H__

#include "ErrorCommon.h"

namespace ErrorHandling {

class IErrorHandler;

//
// Class:	    Error
//
// Description:	Error base class. Derived classes should add pertinant error
//              information, which is accessed via double dispatch with the
//              error handler.
//
// Author:	    Jonathan Waltz
//
class IError;
typedef boost::shared_ptr<IError> IErrorSP;
class IError : public std::exception
{
public:

	//
	// Convenient way to release ownership of shared pointer while passing it to another method.
	//
	template<typename ERROR_SP_T>
	static IErrorSP ReleaseOwnership(ERROR_SP_T& msg)
	{
		IErrorSP retVal = msg;
		msg.reset();
		return retVal;
	}

	//
	// Polymorphic class must implement virtual destructor.
	//
	virtual ~IError() {}

	//
	// method : raise
	//
	// decription : Derived classes must implement as: throw *this;  // Throw this as most derived type!
	//              See: http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.10
	//
	virtual void raise() = 0;

	//
	// method : clone
	//
	// returns : IErrorSP: shared pointer to copy of this.
	//
	// decription : Derived classes must implement as: return IErrorSP(new MostDerivedType(*this));
	//              See: http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8
	//
	virtual IErrorSP clone() const throw() = 0;

	// 
	// method : what
	//
	// returns : c-style string 
	//
	// description : This should return an error message representing the error
	//               in a human-readable fashion - possibly with embedded parameters
	//
	virtual const char* what() const throw() = 0;

	//
	// method : toString
	//
	// returns : string representation of error
	//
	// description : this should return an std::string version of the string returned
	//               from the what() method.
	//
	virtual std::string toString() const throw() = 0;

	//
	// method : getName
	//
	// returns : string name
	//
	// description : this should return a string literal error name
	//
	virtual const char* getName() const throw() { return "IError"; }

	// 
	// method : getId
	//
	// returns : the unique error ID
	//
	// description : see the ErrorIds.h header for coordination of
	//               IDs to maintain uniqueness.
	//
	virtual const ErrorId getId() const throw() = 0;

	// 
	// method : getId
	//
	// returns : the unique error ID
	//
	// description : see the ErrorIds.h header for coordination of
	//               IDs to maintain uniqueness.
	//
	virtual const ErrorSeverity getSeverity() const throw() = 0;

	//
	// method : setSeverity
	//
	// descruption : sets the severity
	//
	virtual void setSeverity( ErrorSeverity sev ) throw() = 0;

	// 
	// method : getTimeStamp
	//
	// returns : the error occurance timestamp
	//
	// description : The timestamp is recorded at error instantiation
	//               and should be as close to the actual incidence of
	//               the error as possible.
	//
	virtual const ErrorTimeStamp getTimeStamp() const throw() = 0;

	// 
	// method : getCause
	//
	// returns : an error shared pointer
	//
	// description : the returned error is the cause of this error, or an empty
	//               shared pointer if this is the root error in a chain.
	//
	virtual const ::boost::shared_ptr<IError> getCause() const throw() = 0;

	//
	// method : setCause
	//
	// descruption : sets the cause
	//
	virtual void setCause( IErrorSP cause ) throw() = 0;

	// 
	// method : getDescription
	//
	// returns : Description of the error.
	//
	virtual std::string getDescription() const throw() = 0;

	// 
	// method : setSourceObject
	//
	// returns : Set name of object that generated error.
	//
	virtual void setSourceObjectName(std::string) throw() = 0;

	// 
	// method : getSourceObject
	//
	// description : Get name of object that generated error.
	//
	virtual std::string getSourceObjectName() const throw() = 0;

	//
	// method : isSafe
	//
	// description : Return true if all smart pointer attributes are unique.
	//
	virtual bool isSafe() const throw() = 0;

	// no real serialization required - specify a vestigial one
	// See http://www.boost.org/doc/libs/1_33_1/libs/serialization/doc/serialization.html#runtimecasting
    template<class Archive>
    void serialize(Archive & ar, const unsigned int file_version){}

};

} // end namespace ErrorHandling

#endif // __IERROR_H__
